package com.java.code.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class SocketChannelServer {
    private static final int BUF_SIZE = 1024;
    private static final int PORT = 1234;

    private ServerSocketChannel servSocketChannel = null;
    private Selector selector = null;

    public static void main(String[] args) {
        new SocketChannelServer().startServer();
    }

    public void startServer() {
        try {
            servSocketChannel = ServerSocketChannel.open();
            // 设置为非阻塞
            servSocketChannel.configureBlocking(false);
            // 绑定端口
            servSocketChannel.socket().bind(new InetSocketAddress(PORT));
            selector = Selector.open();
            // 注册监听事件
            servSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            listen();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void listen() {
        while (true) {
            try {
                //
                selector.select();
                Iterator<SelectionKey> iter = selector.selectedKeys().iterator();

                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    if (key.isValid() && key.isAcceptable()) {
                        System.out.println("handleAccept");
                        handleAccept(key);
                    }
                    if (key.isValid() && key.isReadable()) {
                        System.out.println("handleRead");
                        handleRead(key);
                    }
                    if (key.isValid() && key.isWritable()) {
                        System.out.println("handleWrite");
                        handleWrite(key);
                    }
                    if (key.isValid() && key.isConnectable()) {
                        System.out.println("isConnectable = true");
                    }
                    iter.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static void handleAccept(SelectionKey key) throws IOException {
        ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
        SocketChannel sc = ssChannel.accept();
        sc.configureBlocking(false);
        sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocateDirect(BUF_SIZE));
    }

    public static void handleRead(SelectionKey key) throws IOException {
        SocketChannel sc = (SocketChannel) key.channel();
        try {
            ByteBuffer buf = (ByteBuffer) key.attachment();

            ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
            int bytesRead = sc.read(buf);
            if (bytesRead > 0) {
                buf.flip();
                byte[] bytes = new byte[bytesRead];
                buf.get(bytes, 0, bytesRead);
                String str = new String(bytes);
                System.out.println(str);
                buf.clear();

                writeBuffer.put(bytes);
                writeBuffer.flip();
                while (writeBuffer.hasRemaining()) {
                    sc.write(writeBuffer);
                }
                writeBuffer.compact();

            } else {
                System.out.println("关闭的连接");
                key.cancel();
                sc.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
            key.cancel();
            sc.close();
        }

    }

    public static void handleWrite(SelectionKey key) throws IOException {
        ByteBuffer buf = (ByteBuffer) key.attachment();
        buf.put("客户端返回".getBytes());
        buf.flip();
        SocketChannel sc = (SocketChannel) key.channel();
        while (buf.hasRemaining()) {
            sc.write(buf);
        }
        buf.compact();
    }
}
